package org.dcarew.logviewer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

/**
 * The activator class controls the plug-in life cycle
 */
public class LogViewerPlugin
    extends AbstractUIPlugin
{
	// The plug-in ID
	public static final String PLUGIN_ID = "org.dcarew.logviewer";

	// The shared instance
	private static LogViewerPlugin plugin;
	
    private static Map<String, Image> imageMap  = new HashMap<String, Image>();
    
    
    private List<IEclipseLaunchListener> listeners = new ArrayList<IEclipseLaunchListener>();
    
    private ILaunchesListener2 launchListener = new LaunchesListener2();
    
    
	/**
	 * The constructor
	 */
	public LogViewerPlugin()
	{
	    
	}

	public void start(BundleContext context)
	    throws Exception
	{
		super.start(context);
		
		plugin = this;
		
		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener);
	}

	public void stop(BundleContext context)
	    throws Exception
	{
        DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(launchListener);
        
		plugin = null;
		
		super.stop(context);
	}
	
	
	
    
    /**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static LogViewerPlugin getPlugin()
	{
		return plugin;
	}
	
	public void addEclipseLaunchListener(IEclipseLaunchListener listener)
	{
	    listeners.add(listener);
	}
	
	public void removeEclipseLaunchListener(IEclipseLaunchListener listener)
	{
	    listeners.remove(listener);
	}
	
    /**
     * Get a image from this plugin's icons directory.
     * 
     * @param imagePath the image path, relative to the icons directory.
     * @return the specified image
     */
    public static Image getImage(String imagePath)
    {
        if (imageMap.get(imagePath) == null)
        {
            ImageDescriptor imageDescriptor = imageDescriptorFromPlugin(PLUGIN_ID, "icons/" + imagePath);

            imageMap.put(imagePath, imageDescriptor.createImage());
        }

        return imageMap.get(imagePath);
    }





    /**
     * Get a image descriptor from this plugin's icons directory.
     * 
     * @param imagePath the image path, relative to the icons directory.
     * @return the specified image descriptor
     */
    public static ImageDescriptor getImageDescriptor(String imagePath)
    {
        return imageDescriptorFromPlugin(PLUGIN_ID, "icons/" + imagePath);
    }
    
    public static void log(Throwable exception)
    {
        getPlugin().getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, exception.getMessage(), exception));
    }
    

    private void ensureLogViewerViewExists()
    {
        getWorkbench().getDisplay().asyncExec(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    IWorkbench wb = getWorkbench();
                    IWorkbenchWindow ww = wb.getActiveWorkbenchWindow();
                    IWorkbenchPage wp = ww.getActivePage();
                    
                    //wp.showView(LogViewerView.ID, null, IWorkbenchPage.VIEW_CREATE);
                    wp.showView(LogViewerView.ID, null, IWorkbenchPage.VIEW_VISIBLE);
                }
                catch (PartInitException e)
                {
                    log(e);
                }
            }
        });        
    }
    
    private class LaunchesListener2
        implements ILaunchesListener2
    {
        private Set<ILaunch> runningLaunches = new HashSet<ILaunch>();
        
        @Override
        public void launchesAdded(ILaunch[] launches)
        {
            for (ILaunch launch : launches)
            {
                try
                {
                    if (isEclipseLaunch(launch))
                    {
                        if (runningLaunches.contains(launch))
                            continue;
                        
                        runningLaunches.add(launch);
                        
                        ensureLogViewerViewExists();
                        
                        ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
                        
                        for (IEclipseLaunchListener listener : listeners)
                        {
                            listener.launchStarted(launch, launchConfiguration);
                        }
                    }
                }
                catch (CoreException ce)
                {
                   log(ce);
                }
            }
        }
        
        private boolean isEclipseLaunch(ILaunch launch)
            throws CoreException
        {
            ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
            
            if (launchConfiguration == null)
                return false;
            
            return "Eclipse Application".equals(launchConfiguration.getType().getName());
        }

        @Override
        public void launchesChanged(ILaunch[] launches)
        {
            
        }
        
        @Override
        public void launchesRemoved(ILaunch[] launches)
        {
            for (ILaunch launch : launches)
            {
                try
                {
                    if (isEclipseLaunch(launch))
                    {
                        if (!runningLaunches.contains(launch))
                            continue;
                        
                        runningLaunches.remove(launch);
                        
                        ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
                        
                        for (IEclipseLaunchListener listener : listeners)
                        {
                            listener.launchEnded(launch, launchConfiguration);
                        }
                    }
                }
                catch (CoreException ce)
                {
                   log(ce);
                }
            }
        }
        
        @Override
        public void launchesTerminated(ILaunch[] launches)
        {
            for (ILaunch launch : launches)
            {
                try
                {
                    if (isEclipseLaunch(launch))
                    {
                        if (!runningLaunches.contains(launch))
                            continue;
                        
                        runningLaunches.remove(launch);
                        
                        ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
                        
                        for (IEclipseLaunchListener listener : listeners)
                        {
                            listener.launchEnded(launch, launchConfiguration);
                        }
                    }
                }
                catch (CoreException ce)
                {
                   log(ce);
                }
            }
        }
    }

}
